package com.eastfair.questionnaire.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.eastfair.config.api.DisplayLocationQuestionConfigServiceFeign;
import com.eastfair.config.api.DisplayLocationQuestionnaireConfigServiceFeign;
import com.eastfair.config.entity.DisplayLocationQuestionConfig;
import com.eastfair.config.entity.DisplayLocationQuestionnaireConfig;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.questionnaire.dto.DisplayLocationQuestionDTO;
import com.eastfair.questionnaire.dto.DisplayLocationQuestionnaireDTO;
import com.eastfair.questionnaire.service.DisplayLocationService;
import com.eastfair.questionnaire.service.QuestionService;
import com.eastfair.questionnaire.service.QuestionnaireService;
import com.eastfair.questionnaire.vo.DynamicQuestionnaireVO;
import com.eastfair.questionnaire.vo.QuestionVO;
import com.eastfair.questionnaire.vo.QuestionnaireVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName DisplayLocationServiceImpl
 * @Description TODO
 * @Author yuwx
 * @Date 2021/12/2 9:32
 * @Version 1.0
 **/
@Slf4j
@Service
public class DisplayLocationServiceImpl implements DisplayLocationService {
    private DisplayLocationQuestionConfigServiceFeign displayLocationQuestionConfigServiceFeign;
    private DisplayLocationQuestionnaireConfigServiceFeign displayLocationQuestionnaireConfigServiceFeign;
    private QuestionService questionService;
    private QuestionnaireService questionnaireService;

    @Autowired
    public DisplayLocationServiceImpl(DisplayLocationQuestionConfigServiceFeign displayLocationQuestionConfigServiceFeign, DisplayLocationQuestionnaireConfigServiceFeign displayLocationQuestionnaireConfigServiceFeign, QuestionService questionService, QuestionnaireService questionnaireService) {
        this.displayLocationQuestionConfigServiceFeign = displayLocationQuestionConfigServiceFeign;
        this.displayLocationQuestionnaireConfigServiceFeign = displayLocationQuestionnaireConfigServiceFeign;
        this.questionService = questionService;
        this.questionnaireService = questionnaireService;
    }

    @Override
    public void addDisplayLocationQuestionnaire(String displayLocation, Long questionnaireId) {
        R<List<DisplayLocationQuestionnaireConfig>> result = displayLocationQuestionnaireConfigServiceFeign.getList(new DisplayLocationQuestionnaireConfig());
        List<DisplayLocationQuestionnaireConfig> displayLocationQuestionnaireConfigList = result.getData();
        if (!CollectionUtil.isEmpty(displayLocationQuestionnaireConfigList)
                && displayLocationQuestionnaireConfigList.stream().filter(displayLocationQuestionnaireConfig -> displayLocationQuestionnaireConfig.getDisplayLocation().equalsIgnoreCase(displayLocation)).count() > 0) {
            throw new BizException("相同位置重复添加");
        }
        DisplayLocationQuestionnaireConfig displayLocationQuestionnaireConfig =
                DisplayLocationQuestionnaireConfig.builder()
                        .displayLocation(displayLocation)
                        .questionnaireId(questionnaireId)
                        .createTime(LocalDateTime.now())
                        .createdBy(ContextUtil.getUserId())
                        .build();
        displayLocationQuestionnaireConfigServiceFeign.saveEntity(displayLocationQuestionnaireConfig);

    }

    //todo 事务
    @Override
    public void updateDisplayLocationQuestionnaire(Long displayLocationQuestionnaireId, Long questionnaireId) {
        R<DisplayLocationQuestionnaireConfig> result = displayLocationQuestionnaireConfigServiceFeign.getDisplayLocationQuestionnaireConfig(displayLocationQuestionnaireId);
        DisplayLocationQuestionnaireConfig displayLocationQuestionnaireConfigOld = result.getData();
        if (Objects.isNull(displayLocationQuestionnaireConfigOld)) {
            throw new BizException("数据不存在");
        }
        if (displayLocationQuestionnaireConfigOld.getQuestionnaireId().equals(questionnaireId)) {
            return;
        }

        List<DisplayLocationQuestionDTO> displayLocationQuestionDTOList = listDisplayLocationQuestion(displayLocationQuestionnaireId);
        //更新问卷，删除原有的问题
        displayLocationQuestionDTOList.parallelStream().forEach(displayLocationQuestionDTO -> displayLocationQuestionConfigServiceFeign.deleteEntity(displayLocationQuestionDTO.getId()));
        DisplayLocationQuestionnaireConfig displayLocationQuestionnaireConfig =
                DisplayLocationQuestionnaireConfig.builder()
                        .questionnaireId(questionnaireId)
                        .flagId(displayLocationQuestionnaireId)
                        .updateTime(LocalDateTime.now())
                        .updateBy(ContextUtil.getUserId())
                        .build();
        displayLocationQuestionnaireConfigServiceFeign.updateEntity(displayLocationQuestionnaireConfig);


    }

    @Override
    public List<DisplayLocationQuestionnaireDTO> listDisplayLocationQuestionnaire() {
        R<List<DisplayLocationQuestionnaireConfig>> result = displayLocationQuestionnaireConfigServiceFeign.getList(new DisplayLocationQuestionnaireConfig());
        List<DisplayLocationQuestionnaireConfig> displayLocationQuestionnaireConfigList = result.getData();
        if (CollectionUtil.isEmpty(displayLocationQuestionnaireConfigList)) {
            return Collections.emptyList();
        }
        List<DisplayLocationQuestionnaireDTO> displayLocationQuestionnaireDTOList =
                ConvertUtil.convertList(displayLocationQuestionnaireConfigList, DisplayLocationQuestionnaireDTO.class);
        displayLocationQuestionnaireDTOList.stream().forEach(displayLocationQuestionnaireDTO -> displayLocationQuestionnaireDTO.setId(displayLocationQuestionnaireDTO.getFlagId()));
        return displayLocationQuestionnaireDTOList;
    }

    @Override
    public DynamicQuestionnaireVO getQuestionnaireByDisplayLocation(String displayLocation, String subjectType, Long subjectId) {
        DynamicQuestionnaireVO dynamicQuestionnaireVO = new DynamicQuestionnaireVO();
        dynamicQuestionnaireVO.setQuestionMap(Collections.EMPTY_MAP);
        Optional<DisplayLocationQuestionnaireDTO> optional = getByDisplayLocation(displayLocation);
        if (!optional.isPresent()) {
            return dynamicQuestionnaireVO;
        }
        return questionnaireService.getDynamicWithAnswerResult(ContextUtil.getProjectId(), optional.get().getQuestionnaireId(), subjectType, subjectId);
    }

    @Override
    public QuestionnaireVO getOptionByDisplayLocation(String displayLocation, String subjectType, Long subjectId) {
        QuestionnaireVO questionnaireVO = new QuestionnaireVO();
        Optional<DisplayLocationQuestionnaireDTO> optional = getByDisplayLocation(displayLocation);
        if (!optional.isPresent()) {
            return questionnaireVO;
        }
        List<DisplayLocationQuestionDTO> displayLocationQuestionDTOList = listDisplayLocationQuestion(optional.get().getId());
        final Map<Long, DisplayLocationQuestionDTO> displayLocationQuestionDTOMap = convertDisplayLocationQuestionMap(displayLocationQuestionDTOList);
        questionnaireVO = questionnaireService.getCompleteWithAnswerResult(ContextUtil.getProjectId(), optional.get().getQuestionnaireId(), subjectType, subjectId);
        List<QuestionVO> questionVOList = questionnaireVO.getQuestionList().stream().filter(questionVO -> {
            DisplayLocationQuestionDTO displayLocationQuestionDTO = displayLocationQuestionDTOMap.get(questionVO.getId());
            if (Objects.isNull(displayLocationQuestionDTO) || displayLocationQuestionDTO.getIsEnabled() != BusinessConstant.YES) {
                return false;
            }
            return true;
        }).peek(questionVO -> {
            DisplayLocationQuestionDTO displayLocationQuestionDTO = displayLocationQuestionDTOMap.get(questionVO.getId());
            questionVO.setSelectLower(displayLocationQuestionDTO.getSelectLower());
            questionVO.setSelectUpper(displayLocationQuestionDTO.getSelectUpper());
            questionVO.setSequence(displayLocationQuestionDTO.getSequence());
        }).sorted(Comparator.comparing(QuestionVO::getSequence)).collect(Collectors.toList());
        questionnaireVO.setQuestionList(questionVOList);
        return questionnaireVO;
    }

    @Override
    public void addDisplayLocationQuestion(DisplayLocationQuestionDTO displayLocationQuestionDTO) {
        DisplayLocationQuestionConfig displayLocationQuestionConfig = DisplayLocationQuestionConfig.builder()
                .displayLocationQuestionnaireId(displayLocationQuestionDTO.getDisplayLocationQuestionnaireId())
                .questionId(displayLocationQuestionDTO.getQuestionId())
                .isEnabled(displayLocationQuestionDTO.getIsEnabled())
                .selectLower(displayLocationQuestionDTO.getSelectLower())
                .selectUpper(displayLocationQuestionDTO.getSelectUpper())
                .sequence(displayLocationQuestionDTO.getSequence())
                .createdBy(ContextUtil.getUserId())
                .createTime(LocalDateTime.now()).build();

        R<List<DisplayLocationQuestionConfig>> existResult = displayLocationQuestionConfigServiceFeign.getList(DisplayLocationQuestionConfig.builder()
                .questionId(displayLocationQuestionDTO.getQuestionId())
                .displayLocationQuestionnaireId(displayLocationQuestionDTO.getDisplayLocationQuestionnaireId())
                .build());
        List<DisplayLocationQuestionConfig> existList = existResult.getData();
        if (!CollectionUtil.isEmpty(existList)) {
            displayLocationQuestionConfig.setFlagId(existList.get(0).getFlagId());
            displayLocationQuestionConfigServiceFeign.updateEntity(displayLocationQuestionConfig);
            return;
        }

        displayLocationQuestionConfigServiceFeign.saveEntity(displayLocationQuestionConfig);
    }

    @Override
    public void updateDisplayLocationQuestion(DisplayLocationQuestionDTO displayLocationQuestionDTO) {
        DisplayLocationQuestionConfig displayLocationQuestionConfig = DisplayLocationQuestionConfig.builder()
                .flagId(displayLocationQuestionDTO.getId())
                .displayLocationQuestionnaireId(displayLocationQuestionDTO.getDisplayLocationQuestionnaireId())
                .questionId(displayLocationQuestionDTO.getQuestionId())
                .isEnabled(displayLocationQuestionDTO.getIsEnabled())
                .selectLower(displayLocationQuestionDTO.getSelectLower())
                .selectUpper(displayLocationQuestionDTO.getSelectUpper())
                .sequence(displayLocationQuestionDTO.getSequence())
                .updateBy(ContextUtil.getUserId())
                .updateTime(LocalDateTime.now()).build();
        displayLocationQuestionConfigServiceFeign.saveEntity(displayLocationQuestionConfig);
    }

    @Override
    public List<DisplayLocationQuestionDTO> listWrapDisplayLocationQuestion(Long displayLocationQuestionnaireId) {
        R<DisplayLocationQuestionnaireConfig> displayLocationQuestionnaireConfigResult = displayLocationQuestionnaireConfigServiceFeign.getDisplayLocationQuestionnaireConfig(displayLocationQuestionnaireId);
        DisplayLocationQuestionnaireConfig displayLocationQuestionnaireConfig = displayLocationQuestionnaireConfigResult.getData();
        if (Objects.isNull(displayLocationQuestionnaireConfig)) {
            throw new BizException("位置信息已经不存在");
        }

        List<QuestionVO> questionList = questionService.list(ContextUtil.getProjectId(), displayLocationQuestionnaireConfig.getQuestionnaireId());
        if (CollectionUtil.isEmpty(questionList)) {
            return Collections.emptyList();
        }

        List<DisplayLocationQuestionDTO> displayLocationQuestionDTOList = listDisplayLocationQuestion(displayLocationQuestionnaireId);
        final Map<Long, DisplayLocationQuestionDTO> displayLocationQuestionDTOMap = convertDisplayLocationQuestionMap(displayLocationQuestionDTOList);

        return questionList.stream().map(questionVO -> {
            DisplayLocationQuestionDTO displayLocationQuestionDTO = displayLocationQuestionDTOMap.get(questionVO.getId());
            if (!Objects.isNull(displayLocationQuestionDTO)) {
                displayLocationQuestionDTO.setId(displayLocationQuestionDTO.getFlagId());
                return displayLocationQuestionDTO;
            }
            displayLocationQuestionDTO = DisplayLocationQuestionDTO.builder()
                    .displayLocationQuestionnaireId(displayLocationQuestionnaireId)
                    .isEnabled(BusinessConstant.ENABLE_NO)
                    .selectLower(questionVO.getSelectLower())
                    .selectUpper(questionVO.getSelectUpper())
                    .sequence(questionVO.getSequence())
                    .questionId(questionVO.getId())
                    .build();
            return displayLocationQuestionDTO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<DisplayLocationQuestionDTO> listDisplayLocationQuestion(Long displayLocationQuestionnaireId) {
        R<List<DisplayLocationQuestionConfig>> result = displayLocationQuestionConfigServiceFeign.getList(DisplayLocationQuestionConfig.builder().displayLocationQuestionnaireId(displayLocationQuestionnaireId).build());
        List<DisplayLocationQuestionConfig> displayLocationQuestionConfigList = result.getData();
        List<DisplayLocationQuestionDTO> displayLocationQuestionDTOList = ConvertUtil.convertList(displayLocationQuestionConfigList, DisplayLocationQuestionDTO.class);
        displayLocationQuestionDTOList.stream().forEach(displayLocationQuestionDTO -> displayLocationQuestionDTO.setId(displayLocationQuestionDTO.getFlagId()));
        return displayLocationQuestionDTOList;
    }

    /**
     * Description 转换map
     *
     * @param displayLocationQuestionDTOList
     * @return java.util.Map<java.lang.Long, com.eastfair.questionnaire.dto.DisplayLocationQuestionDTO>
     * @Date 11:38 2021/12/3
     * @Author yuwx
     **/
    private Map<Long, DisplayLocationQuestionDTO> convertDisplayLocationQuestionMap(List<DisplayLocationQuestionDTO> displayLocationQuestionDTOList) {
        if (CollectionUtil.isEmpty(displayLocationQuestionDTOList)) {
            return Collections.emptyMap();
        }

        return displayLocationQuestionDTOList.stream().collect(Collectors.toMap(DisplayLocationQuestionDTO::getQuestionId, o -> o, (o, n) -> o));
    }

    /**
     * Description 根据位置获取问卷
     *
     * @param displayLocation
     * @return java.util.Optional<com.eastfair.questionnaire.dto.DisplayLocationQuestionnaireDTO>
     * @Date 17:22 2021/12/7
     * @Author yuwx
     **/
    private Optional<DisplayLocationQuestionnaireDTO> getByDisplayLocation(String displayLocation) {
        List<DisplayLocationQuestionnaireDTO> displayLocationQuestionnaireDTOList = listDisplayLocationQuestionnaire();
        if (Objects.isNull(displayLocationQuestionnaireDTOList) || StrUtil.isBlank(displayLocation)) {
            return Optional.empty();
        }
        Optional<DisplayLocationQuestionnaireDTO> optional = displayLocationQuestionnaireDTOList.stream().filter(displayLocationQuestionnaireDTO ->
                StrUtil.equals(displayLocationQuestionnaireDTO.getDisplayLocation(), displayLocation, true)
                        && !Objects.isNull(displayLocationQuestionnaireDTO.getQuestionnaireId()))
                .findFirst();
        return optional;
    }
}
